﻿using System;
using System.Collections.Generic;
using System.Text;

namespace Diagrams
{
    /// <summary>
    /// Класс, сохраняющий предыдущие состояния диаграммы для Undo/Redo
    /// </summary>
    public class DiagramMemento
    {
        //список емкостью 10 состояний диаграммы
        private List<Diagram> mementoStack = new List<Diagram>(10);
        //делегат, вызывающийся для сохранения состояния логики диаграммы
        public delegate void MemorizeLogicDelegate();
        public MemorizeLogicDelegate MemorizeLogic;
        //делегаты на Undo/Redo
        public delegate void UndoLogicDelegate();
        public UndoLogicDelegate UndoLogic;
        public delegate void RedoLogicDelegate();
        public RedoLogicDelegate RedoLogic;
        //делегат, вызывающий событие изменения состояния диаграммы
        public delegate void DiagramChangeDelegate();
        public DiagramChangeDelegate DiagramChange;

        private int currentState = -1;
        /// <summary>
        /// Показывает, можно ли откатить диаграмму вперед
        /// </summary>
        public bool CanRedo
        {
            get
            {
                if (currentState < mementoStack.Count - 1)
                    return true;
                return false;
            }
        }
        /// <summary>
        /// Показывает, можно ли откатить диаграмму назад
        /// </summary>
        public bool CanUndo
        {
            get
            {
                if (currentState < 1)
                    return false;
                return true;
            }
        }
        /// <summary>
        /// Запоминает текущее состояние диаграммы
        /// </summary>
        public void Memorize(Diagram diagram)
        {
            if (diagram == null)
                return;
            //увеличиваем счетчик состояния
            currentState++;
            //если текущее состояние - не последнее (было Undo), удаляем все последюущие
            if (currentState < mementoStack.Count)
                mementoStack.RemoveRange(currentState, mementoStack.Count - currentState);

            //если текущее состояние - последнее возможное, удаляем первое запомненное
            if (currentState == mementoStack.Capacity)
            {
                mementoStack.RemoveAt(0);
                currentState--;
            }
            //запоминаем копию
            mementoStack.Add(diagram.Clone() as Diagram);
            //сообщаем, что состояние диаграммы изменилось
            if(DiagramChange != null)
                DiagramChange();
            //запоминаем состояние логики
            if (MemorizeLogic != null)
            {//если делегат существует, запоминаем его
                MemorizeLogic();
            }
        }
        /// <summary>
        /// Восстанавливает предыдущее состояние диаграммы
        /// </summary>
        /// <param name="diagram"></param>
        public void Undo(ref Diagram diagram)
        {
            
            if (currentState > 0)
            {
                currentState--;
                diagram = mementoStack[currentState].Clone() as Diagram;
                //сообщаем, что состояние диаграммы изменилось
                if (DiagramChange != null)
                    DiagramChange();
            }
            UndoLogic();
        }
        /// <summary>
        /// Возвращает следующее состояние диаграммы
        /// </summary>
        /// <param name="diagram"></param>
        public void Redo(ref Diagram diagram)
        {
            if (currentState < mementoStack.Count - 1)
            {
                currentState++;
                diagram = mementoStack[currentState].Clone() as Diagram;
                //сообщаем, что состояние диаграммы изменилось
                if (DiagramChange != null)
                    DiagramChange();
            }
            RedoLogic();
        }
    }
}
